package com.shipdream.lib.ohos.mvc.samples.simple;

import com.shipdream.lib.ohos.mvc.MvcGraph;
import com.shipdream.lib.ohos.mvc.samples.simple.controller.*;
import com.shipdream.lib.ohos.mvc.samples.simple.controller.internal.*;
import com.shipdream.lib.ohos.mvc.samples.simple.service.*;
import com.shipdream.lib.ohos.mvc.samples.simple.service.internal.*;
import com.shipdream.lib.poke.ProviderByClassType;
import com.shipdream.lib.poke.exception.ProviderConflictException;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.Text;

import javax.inject.Inject;

public class MainAbility extends Ability implements Component.ClickedListener {

    private Text textDagger10;
    private Text textPokePattern10;
    private Text textPokeRegistry10;
    private Text textDagger10x10;
    private Text textPokePattern10x10;
    private Text textPokeRegistry10x10;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        textDagger10 = (Text) findComponentById(ResourceTable.Id_text_dagger_inject10);
        textPokePattern10 = (Text) findComponentById(ResourceTable.Id_text_poke_pattern_inject10);
        textPokeRegistry10 = (Text) findComponentById(ResourceTable.Id_text_poke_registry_inject10);
        textDagger10x10 = (Text) findComponentById(ResourceTable.Id_text_dagger_inject10x10);
        textPokePattern10x10 = (Text) findComponentById(ResourceTable.Id_text_poke_pattern_inject10x10);
        textPokeRegistry10x10 = (Text) findComponentById(ResourceTable.Id_text_poke_registry_inject10x10);
        findComponentById(ResourceTable.Id_button_dagger_inject10).setClickedListener(this);
        findComponentById(ResourceTable.Id_button_dagger_inject10x10).setClickedListener(this);
        findComponentById(ResourceTable.Id_button_poke_registry_inject10).setClickedListener(this);
        findComponentById(ResourceTable.Id_button_poke_registry_inject10x10).setClickedListener(this);
        findComponentById(ResourceTable.Id_button_poke_pattern_inject10).setClickedListener(this);
        findComponentById(ResourceTable.Id_button_poke_pattern_inject10x10).setClickedListener(this);
    }

    @Override
    public void onClick(Component component) {
        int id = component.getId();
        if (id == ResourceTable.Id_button_dagger_inject10) {
            func1();
        } else if (id == ResourceTable.Id_button_dagger_inject10x10) {
            func2();
        } else if (id == ResourceTable.Id_button_poke_registry_inject10) {
            func3();
        } else if (id == ResourceTable.Id_button_poke_registry_inject10x10) {
            func4();
        } else if (id == ResourceTable.Id_button_poke_pattern_inject10) {
            func5();
        } else if (id == ResourceTable.Id_button_poke_pattern_inject10x10) {
            func6();
        } else {

        }
    }

    private void func1() {
        Container10 container = new Container10();

        long ts = System.currentTimeMillis();
        ControllerComponent comp = DaggerControllerComponent.builder()
                .controllerModule(new ControllerModule()).build();
        comp.inject(container);
        long elapsed = System.currentTimeMillis() - ts;
        textDagger10.setText(String.format("Dagger inject 10 fields used %dms", elapsed));
    }

    private void func2() {
        Container10x10 container = new Container10x10();

        long ts = System.currentTimeMillis();
        ControllerComponent comp = DaggerControllerComponent.builder()
                .controllerModule(new ControllerModule()).build();
        comp.inject(container);
        comp.inject((Controller0Impl) container.controller0);
        comp.inject((Controller1Impl) container.controller1);
        comp.inject((Controller2Impl) container.controller2);
        comp.inject((Controller3Impl) container.controller3);
        comp.inject((Controller4Impl) container.controller4);
        comp.inject((Controller5Impl) container.controller5);
        comp.inject((Controller6Impl) container.controller6);
        comp.inject((Controller7Impl) container.controller7);
        comp.inject((Controller8Impl) container.controller8);
        comp.inject((Controller9Impl) container.controller9);

        long elapsed = System.currentTimeMillis() - ts;
        textDagger10x10.setText(String.format("Dagger inject 10x10 nested fields used %dms", elapsed));
    }

    private void func3() {
        Container10 container = new Container10();

        long ts = System.currentTimeMillis();
        try {
            MvcGraph graph = new MvcGraph();

            register(graph, Service0.class, Service0Impl.class);
            register(graph, Service1.class, Service1Impl.class);
            register(graph, Service2.class, Service2Impl.class);
            register(graph, Service3.class, Service3Impl.class);
            register(graph, Service4.class, Service4Impl.class);
            register(graph, Service5.class, Service5Impl.class);
            register(graph, Service6.class, Service6Impl.class);
            register(graph, Service7.class, Service7Impl.class);
            register(graph, Service8.class, Service8Impl.class);
            register(graph, Service9.class, Service9Impl.class);

            graph.inject(container);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        long elapsed = System.currentTimeMillis() - ts;
        textPokeRegistry10.setText(String.format("Poke inject 10 fields by registry used %dms",
                elapsed));
    }

    private void func4() {
        Container10x10 container = new Container10x10();

        long ts = System.currentTimeMillis();
        try {
            MvcGraph graph = new MvcGraph();

            register(graph, Controller0.class, Controller0Impl.class);
            register(graph, Controller1.class, Controller1Impl.class);
            register(graph, Controller2.class, Controller2Impl.class);
            register(graph, Controller3.class, Controller3Impl.class);
            register(graph, Controller4.class, Controller4Impl.class);
            register(graph, Controller5.class, Controller5Impl.class);
            register(graph, Controller6.class, Controller6Impl.class);
            register(graph, Controller7.class, Controller7Impl.class);
            register(graph, Controller8.class, Controller8Impl.class);
            register(graph, Controller9.class, Controller9Impl.class);
            register(graph, Service0.class, Service0Impl.class);
            register(graph, Service1.class, Service1Impl.class);
            register(graph, Service2.class, Service2Impl.class);
            register(graph, Service3.class, Service3Impl.class);
            register(graph, Service4.class, Service4Impl.class);
            register(graph, Service5.class, Service5Impl.class);
            register(graph, Service6.class, Service6Impl.class);
            register(graph, Service7.class, Service7Impl.class);
            register(graph, Service8.class, Service8Impl.class);
            register(graph, Service9.class, Service9Impl.class);

            graph.inject(container);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        long elapsed = System.currentTimeMillis() - ts;
        textPokeRegistry10x10.setText(String.format("Poke inject 10x10 nested fields by registry used %dms", elapsed));
    }

    private void func5() {
        Container10 container = new Container10();
        long ts = System.currentTimeMillis();
        try {
            new MvcGraph().inject(container);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        long elapsed = System.currentTimeMillis() - ts;
        textPokePattern10.setText(String.format("Poke inject 10 fields by pattern used %dms", elapsed));
    }

    private void func6() {
        Container10x10 container = new Container10x10();

        long ts = System.currentTimeMillis();
        try {
            new MvcGraph().inject(container);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        long elapsed = System.currentTimeMillis() - ts;
        textPokePattern10x10.setText(String.format("Poke inject 10x10 nested fields by pattern used %dms",
                elapsed));
    }


    private void register(MvcGraph graph, Class type, Class impl) throws ProviderConflictException {
        graph.getRootComponent().register(new ProviderByClassType(type, impl));
    }


    public static class Container10 {
        @Inject
        Service0 service0;
        @Inject
        Service1 service1;
        @Inject
        Service2 service2;
        @Inject
        Service3 service3;
        @Inject
        Service4 service4;
        @Inject
        Service5 service5;
        @Inject
        Service6 service6;
        @Inject
        Service7 service7;
        @Inject
        Service8 service8;
        @Inject
        Service9 service9;
    }

    public static class Container10x10 {
        @Inject
        Controller0 controller0;
        @Inject
        Controller1 controller1;
        @Inject
        Controller2 controller2;
        @Inject
        Controller3 controller3;
        @Inject
        Controller4 controller4;
        @Inject
        Controller5 controller5;
        @Inject
        Controller6 controller6;
        @Inject
        Controller7 controller7;
        @Inject
        Controller8 controller8;
        @Inject
        Controller9 controller9;
    }
}
